home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / strlist3 / strlist.c next >
Text File  |  1996-02-26  |  12KB  |  424 lines

  1. /* File strlist.c Copyright (C) 1995, 1996 by John R. Montbriand.  All Rights Reserved. */
  2.  
  3. /* File strlist.c
  4.  
  5.     Copyright (C) 1995, 1996 by John Montbriand.  All Rights Reserved.
  6.     
  7.     Distribute freely in areas where the laws of copyright apply.
  8.     
  9.     Use at your own risk.
  10.     
  11.     Do not distribute modified copies.
  12.     
  13.     These various string list libraries are for free!
  14.     
  15.     See the file strlist.txt for details.
  16.     
  17. */
  18.  
  19. #include "strlist.h"
  20. #include <Memory.h>
  21. #include <StdLib.h>
  22. #include <OSUtils.h>
  23. #include <ToolUtils.h>
  24. #include <String.h>
  25. #include <Strings.h>
  26. #include <Resources.h>
  27. #include <Script.h>
  28. #include <TextUtils.h>
  29. #include <StdArg.h>
  30.  
  31. Handle NewStringList(void) {
  32.     return NewHandleClear(sizeof(short));
  33. }
  34.  
  35. Handle MakeStringList(long n, ...) {
  36.     va_list args;
  37.     long i;
  38.     char *s;
  39.     Str255 tempstr;
  40.     Handle list;
  41.     if ((list = NewStringList()) != NULL) {
  42.         va_start(args, n);
  43.         for (i=0; i<n; i++) {
  44.             s = va_arg(args, char*);
  45.             StringListAppend(list, c2pstr(strcpy((char*) tempstr, s)));
  46.         }
  47.         va_end(args);
  48.     }
  49.     return list;
  50. }
  51.  
  52. Handle GetStringList(short id) {
  53.     return GetResource('STR#', id);
  54. }
  55.  
  56. Handle Get1StringList(short id) {
  57.     return Get1Resource('STR#', id);
  58. }
  59.  
  60. short StringListSize(Handle list) {
  61.     if (list == NULL)
  62.         return 0;
  63.     else return ** ((short**) list);
  64. }
  65.  
  66. void DisposeStringList(Handle list) {
  67.     char flags;
  68.     if (list != NULL) {
  69.         flags = HGetState(list);
  70.         if ((flags & (1<<5)) != 0) {
  71.             ReleaseResource(list);
  72.         } else {
  73.             DisposeHandle(list);
  74.         }
  75.     }
  76. }
  77.  
  78. StringPtr StringListElt(Handle list, short elt) {
  79.     unsigned char *sp;
  80.     short i, n ;
  81.     if (list != NULL) {
  82.         sp = (unsigned char*) (*list);
  83.         n = ** ((short**) list);
  84.         for (sp+=2, i=1; i<=n; i++, sp += *sp + 1)
  85.             if (i==elt) return sp;
  86.     }
  87.     return NULL;
  88. }
  89.  
  90. StringPtr RetrieveIndString(Handle list, short elt, StringPtr the_string) {
  91.     StringPtr elt_string;
  92.     elt_string = StringListElt(list, elt);
  93.     if (elt_string != NULL) {
  94.         unsigned char *a, *b;
  95.         long j, n;
  96.         a = elt_string;
  97.         b = the_string;
  98.         for (j = 1, n = (*b++ = *a++); j <= n; j++, *b++ = *a++);
  99.         return the_string;
  100.     } else return NULL;
  101. }
  102.  
  103. StringPtr** MakeStringListMap(Handle list) {
  104.     unsigned char *sp;
  105.     short i, n;
  106.     StringPtr** the_array, *rover;
  107.     if (list != NULL) {
  108.         n = ** ((short**) list);
  109.         the_array = (StringPtr**) NewHandle(n * sizeof(StringPtr));
  110.         if (the_array != NULL) {
  111.             MoveHHi(list);
  112.             HLock(list);
  113.             sp = (unsigned char*) (*list);
  114.             rover = *the_array;
  115.             for (sp+=2, i=1; i<=n; i++, sp += *sp + 1) *rover++ = sp;
  116.         }
  117.         return the_array;
  118.     } else return NULL;
  119. }
  120.  
  121. int STRCompare(const void *a, const void *b) {
  122.     return RelString(* ((StringPtr*) a),* ((StringPtr*) b), SLUSECASE, true);
  123. }
  124.  
  125. StringPtr** MakeSortedStringListMap(Handle list) {
  126.     StringPtr** the_map;
  127.     short n;
  128.     the_map = MakeStringListMap(list);
  129.     if (the_map != NULL) {
  130.         n = ** ((short**) list);
  131.         HLock((Handle) the_map);
  132.         qsort(*the_map, n, sizeof(StringPtr), STRCompare);
  133.         HUnlock((Handle) the_map);
  134.     }
  135.     return the_map;
  136. }
  137.  
  138. StringPtr MapStringListElt(StringPtr** string_map, short elt) {
  139.     if (string_map != NULL)
  140.         return (*string_map)[elt-1];
  141.     else return NULL;
  142. }
  143.  
  144. void StringListRemove(Handle list, short elt) {
  145.     unsigned char *sp, *start;
  146.     short i, n;
  147.     if (list != NULL) {
  148.         n = ** ((short**) list);
  149.         sp = start = (unsigned char*) (*list);
  150.         for (sp+=2, i=1; i<=n; i++, sp += *sp + 1)
  151.             if (i==elt) {
  152.                 Munger(list, sp-start, NULL, *sp + 1, &i, 0);
  153.                 (** ((short**) list)) -= 1;
  154.                 break;
  155.             }
  156.     }
  157. }
  158.  
  159. void ClearStringList(Handle list) {
  160.     if (list != NULL) {
  161.         SetHandleSize(list, 2);
  162.         (** ((short**) list)) = 0;
  163.     }
  164. }
  165.  
  166. short StringListInsert(Handle list, StringPtr s) {
  167.     unsigned char *sp, *start;
  168.     short i, n;
  169.     char state;
  170.     if (list != NULL) {
  171.         state = HGetState(list);
  172.         n = ** ((short**) list);
  173.         HLock(list);
  174.         sp = start = (unsigned char*) (*list);
  175.         for (sp+=2, i=1; i<=n; i++, sp += *sp + 1)
  176.             if (RelString(s, sp, SLUSECASE, true) <= 0) break;
  177.         HUnlock(list);
  178.         Munger(list, sp-start, NULL, 0, s, *s + 1);
  179.         (** ((short**) list)) += 1;
  180.         HSetState(list, state);
  181.         return i;
  182.     } else return 0;
  183. }
  184.  
  185. void StringListInstall(Handle list, short elt, StringPtr s) {
  186.     unsigned char *sp, *start;
  187.     short i, n;
  188.     if (list != NULL) {
  189.         n = ** ((short**) list);
  190.         sp = start = (unsigned char*) (*list);
  191.         for (sp+=2, i=1; i<=n; i++, sp += *sp + 1)
  192.             if (i == elt) break;
  193.         Munger(list, sp-start, NULL, 0, s, *s + 1);
  194.         (** ((short**) list)) += 1;
  195.     }
  196. }
  197.  
  198. void StringListAppend(Handle list, StringPtr s) {
  199.     StringListInstall(list, 0x7FFF, s);
  200. }
  201.  
  202. void StringListPrepend(Handle list, StringPtr s) {
  203.     StringListInstall(list, 1, s);
  204. }
  205.  
  206. short StringListRInsert(Handle list, StringPtr s) {
  207.     unsigned char *sp, *start;
  208.     short i, n;
  209.     char state;
  210.     if (list != NULL) {
  211.         n = ** ((short**) list);
  212.         state = HGetState(list);
  213.         HLock(list);
  214.         sp = start = (unsigned char*) (*list);
  215.         for (sp+=2, i=1; i<=n; i++, sp += *sp + 1)
  216.             if (RelString(s, sp, false, true) >= 0) break;
  217.         HUnlock(list);
  218.         Munger(list, sp-start, NULL, 0, s, *s + 1);
  219.         (** ((short**) list)) += 1;
  220.         HSetState(list, state);
  221.         return i;
  222.     } else return 0;
  223. }
  224.  
  225. short FindStringList(Handle list, StringPtr s) {
  226.     unsigned char *sp, *start;
  227.     short i, n;
  228.     char state;
  229.     if (list != NULL) {
  230.         n = ** ((short**) list);
  231.         state = HGetState(list);
  232.         HLock(list);
  233.         sp = start = (unsigned char*) (*list);
  234.         for (sp+=2, i=1; i<=n; i++, sp += *sp + 1)
  235.             if (RelString(s, sp, SLUSECASE, true) == 0) break;
  236.         HSetState(list, state);
  237.         return i <= n ? i : 0;
  238.     } else return 0;
  239. }
  240.  
  241. MenuHandle StringListToMenu(Handle list, short id, StringPtr name) {
  242.     MenuHandle mnu;
  243.     short i, n;
  244.     char state;
  245.     unsigned char *sp;
  246.     if (list != NULL) {
  247.         n = ** ((short**) list);
  248.         state = HGetState(list);
  249.         HLock(list);
  250.         mnu = NewMenu(id, (name==NULL ? "\pSTR#" : name));
  251.         if (mnu != NULL) {
  252.             sp = (unsigned char*) (*list);
  253.             for (sp+=2, i=1; i<=n; i++, sp += *sp + 1) {
  254. #ifdef INTERPRETMENUCHARS
  255.                 AppendMenu(mnu, sp);
  256. #else
  257.                 AppendMenu(mnu, "\pDATA");
  258.                 SetItem(mnu, i, sp);
  259. #endif
  260.             }
  261.         }
  262.         HSetState(list, state);
  263.         return mnu;
  264.     } else return NULL;
  265. }
  266.  
  267. void StringListToList(Handle list, ListHandle the_list) {
  268.     short i, n;
  269.     char state;
  270.     unsigned char* sp;
  271.     Cell theCell;
  272.     if (list != NULL) {
  273.         n = ** ((short**) list);
  274.         LDelRow(0, 0, the_list);
  275.         LAddRow(StringListSize(list), 0, the_list);
  276.         state = HGetState(list);
  277.         HLock(list);
  278.         sp = (unsigned char*) (*list);
  279.         for (sp+=2, i=1; i<=n; i++, sp += *sp + 1) {
  280.             SetPt(&theCell, 0, i-1);
  281.             LSetCell(sp + 1, sp[0], theCell, the_list);
  282.         }
  283.         HSetState(list, state);
  284.     }
  285. }
  286.  
  287.  
  288. Handle StringListUnion(Handle A, Handle B) {
  289.     StringPtr **AMap = NULL, **BMap = NULL, stra, strb;
  290.     Handle result = NULL;
  291.     short acount, bcount, i, j, cmp;
  292.     if ((result = NewStringList()) == NULL) goto union_abort;
  293.     if ((AMap = MakeSortedStringListMap(A)) == NULL) goto union_abort;
  294.     if ((BMap = MakeSortedStringListMap(B)) == NULL) goto union_abort;
  295.     acount = StringListSize(A);
  296.     bcount = StringListSize(B);
  297.     i = j = 0;
  298.     while (i < acount && j < bcount) {
  299.         cmp = RelString((stra = (*AMap)[i]), (strb = (*BMap)[j]),
  300.             SLUSECASE, true);
  301.         if (cmp == 0) {
  302.             StringListAppend(result, stra);
  303.             i++; j++;
  304.         } else if (cmp < 0) {
  305.             StringListAppend(result, stra);
  306.             i++;
  307.         } else {
  308.             StringListAppend(result, strb);
  309.             j++;
  310.         }
  311.     }
  312.     while (i < acount) StringListAppend(result, (*AMap)[i++]);
  313.     while (j < bcount) StringListAppend(result, (*BMap)[j++]);
  314.     DisposeHandle((Handle) AMap); HUnlock(A);
  315.     DisposeHandle((Handle) BMap); HUnlock(B);
  316.     return result;
  317. union_abort:
  318.     if (AMap != NULL) { DisposeHandle((Handle) AMap); HUnlock(A); }
  319.     if (BMap != NULL) { DisposeHandle((Handle) BMap); HUnlock(B); }
  320.     if (result != NULL) DisposeHandle((Handle) result);
  321.     return NULL;
  322. }
  323.  
  324. Handle StringListIntersection(Handle A, Handle B) {
  325.     StringPtr **AMap = NULL, **BMap = NULL, stra, strb;
  326.     Handle result = NULL;
  327.     short acount, bcount, i, j, cmp;
  328.     if ((result = NewStringList()) == NULL) goto union_abort;
  329.     if ((AMap = MakeSortedStringListMap(A)) == NULL) goto union_abort;
  330.     if ((BMap = MakeSortedStringListMap(B)) == NULL) goto union_abort;
  331.     acount = StringListSize(A);
  332.     bcount = StringListSize(B);
  333.     i = j = 0;
  334.     while (i < acount && j < bcount) {
  335.         cmp = RelString((stra = (*AMap)[i]), (strb = (*BMap)[j]),
  336.             SLUSECASE, true);
  337.         if (cmp == 0) {
  338.             StringListAppend(result, stra);
  339.             i++; j++;
  340.         } else if (cmp < 0) i++; else j++;
  341.     }
  342.     DisposeHandle((Handle) AMap); HUnlock(A);
  343.     DisposeHandle((Handle) BMap); HUnlock(B);
  344.     return result;
  345. union_abort:
  346.     if (AMap != NULL) { DisposeHandle((Handle) AMap); HUnlock(A); }
  347.     if (BMap != NULL) { DisposeHandle((Handle) BMap); HUnlock(B); }
  348.     if (result != NULL) DisposeHandle((Handle) result);
  349.     return NULL;
  350. }
  351.  
  352. Handle StringListDifference(Handle A, Handle B) {
  353.     StringPtr **AMap = NULL, **BMap = NULL, stra, strb;
  354.     Handle result = NULL;
  355.     short acount, bcount, i, j, cmp;
  356.     if ((result = NewStringList()) == NULL) goto union_abort;
  357.     if ((AMap = MakeSortedStringListMap(A)) == NULL) goto union_abort;
  358.     if ((BMap = MakeSortedStringListMap(B)) == NULL) goto union_abort;
  359.     acount = StringListSize(A);
  360.     bcount = StringListSize(B);
  361.     i = j = 0;
  362.     while (i < acount && j < bcount) {
  363.         cmp = RelString((stra = (*AMap)[i]), (strb = (*BMap)[j]),
  364.             SLUSECASE, true);
  365.         if (cmp == 0) {
  366.             i++; j++;
  367.         } else if (cmp < 0) {
  368.             StringListAppend(result, stra);
  369.             i++;
  370.         } else {
  371.             StringListAppend(result, strb);
  372.             j++;
  373.         }
  374.     }
  375.     while (i < acount) StringListAppend(result, (*AMap)[i++]);
  376.     while (j < bcount) StringListAppend(result, (*BMap)[j++]);
  377.     DisposeHandle((Handle) AMap); HUnlock(A);
  378.     DisposeHandle((Handle) BMap); HUnlock(B);
  379.     return result;
  380. union_abort:
  381.     if (AMap != NULL) { DisposeHandle((Handle) AMap); HUnlock(A); }
  382.     if (BMap != NULL) { DisposeHandle((Handle) BMap); HUnlock(B); }
  383.     if (result != NULL) DisposeHandle((Handle) result);
  384.     return NULL;
  385. }
  386.  
  387. Boolean StringListSubset(Handle A, Handle B) {
  388.     StringPtr **AMap = NULL, **BMap = NULL, stra, strb;
  389.     Boolean result = true;
  390.     short acount, bcount, i, j, cmp;
  391.     if ((AMap = MakeSortedStringListMap(A)) == NULL) goto union_abort;
  392.     if ((BMap = MakeSortedStringListMap(B)) == NULL) goto union_abort;
  393.     acount = StringListSize(A);
  394.     bcount = StringListSize(B);
  395.     i = j = 0;
  396.     while (i < acount && j < bcount) {
  397.         cmp = RelString((stra = (*AMap)[i]), (strb = (*BMap)[j]),
  398.             SLUSECASE, true);
  399.         if (cmp == 0) {    // in both A and B
  400.             i++; j++;
  401.         } else if (cmp < 0) {    // in A but not in B
  402.             i++;
  403.         } else {    // in B but not in A
  404.             result = false;
  405.             break;
  406.         }
  407.     }
  408.     DisposeHandle((Handle) AMap); HUnlock(A);
  409.     DisposeHandle((Handle) BMap); HUnlock(B);
  410.     return result;
  411. union_abort:
  412.     if (AMap != NULL) { DisposeHandle((Handle) AMap); HUnlock(A); }
  413.     if (BMap != NULL) { DisposeHandle((Handle) BMap); HUnlock(B); }
  414.     return false;
  415. }
  416.  
  417. Boolean StringListEquivalent(Handle A, Handle B) {
  418.     if (StringListSize(A) == StringListSize(B) && StringListSubset(A, B))
  419.         return true;
  420.     else return false;
  421. }
  422.  
  423. /* end of file strlist.c */
  424.